using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace Clarius.PresentationModel.Design.Tests
{
	[System.CodeDom.Compiler.GeneratedCode("XamlBinding", "0.1.0.0")]
	public partial class SupportInitialize :
		ISupportInitialize,
		ISupportInitializeNotification,
		IChangeTracking,
		INotifyPropertyChanged
	{
		private const string InitializationNotBegun = "Initialization has not been started.";
		private const string NotInitialized = "The object has not been initialized properly. Call Initialize prior to use.";

		bool _beginCalled;
		bool _isInitialized;

		bool _isChanged;

		void IChangeTracking.AcceptChanges()
		{
			Initialize();
		}

		bool IChangeTracking.IsChanged
		{
			get { return _isChanged || HasNestedChanges; }
		}

		/// <summary>
		/// Gets whether the object properties that support 
		/// <see cref="IChangeTracking"/> report changes.
		/// </summary>
		[EditorBrowsable(EditorBrowsableState.Never)]
		protected virtual bool HasNestedChanges
		{
			get
			{
				return IsValueChanged(nested as IChangeTracking);
			}
		}

		/// <summary>
		/// Determines whether the value is not null and has changed.
		/// </summary>
		[EditorBrowsable(EditorBrowsableState.Never)]
		protected bool IsValueChanged(IChangeTracking value)
		{
			return value != null && value.IsChanged;
		}

		#region ISupportInitializeNotification

		/// <summary>
		/// Signals that the object has been initialized.
		/// </summary>
		public event EventHandler Initialized;

		bool ISupportInitializeNotification.IsInitialized
		{
			get
			{
				return _isInitialized && AreNestedInitialized;
			}
		}

		/// <summary>
		/// Gets whether the object properties that support 
		/// <see cref="ISupportInitializeNotification"/> are initialized.
		/// </summary>
		[EditorBrowsable(EditorBrowsableState.Never)]
		protected virtual bool AreNestedInitialized
		{
			get
			{
				return true && IsValueInitialized(nested as ISupportInitializeNotification);
			}
		}

		/// <summary>
		/// Determines whether the value is null or its 
		/// <see cref="ISupportInitializeNotification.IsInitialized"/> is <see langword="true" />;
		/// </summary>
		[EditorBrowsable(EditorBrowsableState.Never)]
		protected bool IsValueInitialized(ISupportInitializeNotification value)
		{
			return value == null || value.IsInitialized;
		}

		#endregion

		#region ISupportInitialize

		private bool RequiresInitialize
		{
			get
			{
				return !((ISupportInitializeNotification)this).IsInitialized ||
					((IChangeTracking)this).IsChanged;
			}
		}

		/// <summary>
		/// Validates object properties and initializes it for use.
		/// </summary>
		public void Initialize()
		{
			if (RequiresInitialize)
			{
				DoValidate();
				_isChanged = false;

				// Initialize children.
				InitializeNested();

				DoInitialize();
				_isInitialized = true;

				if (Initialized != null)
				{
					Initialized(this, EventArgs.Empty);
				}
			}
		}

		/// <summary>
		/// Initializes the nested properties that support <see cref="ISupportInitialize"/>.
		/// </summary>
		protected virtual void InitializeNested()
		{
			ISupportInitialize initializable;

			initializable = (ISupportInitialize)nested;
			if (initializable != null)
			{
				initializable.BeginInit();
				initializable.EndInit();
			}
		}

		void ISupportInitialize.BeginInit()
		{
			_beginCalled = true;
		}

		void ISupportInitialize.EndInit()
		{
			if (!_beginCalled)
			{
				throw new InvalidOperationException(InitializationNotBegun);
			}

			Initialize();
		}

		#endregion

		#region INotifyPropertyChanged Members

		public event EventHandler MyPropertyChanged;

		private void RaiseMyPropertyChanged()
		{
			if (MyPropertyChanged != null)
				MyPropertyChanged(this, EventArgs.Empty);

			RaisePropertyChanged("MyProperty");
		}

		/// <summary>
		/// Signals that the property <see cref="NestedSupport"/> has changed.
		/// </summary>
		public event EventHandler NestedSupportChanged;

		private void RaiseNestedSupportChanged()
		{
			if (NestedSupportChanged != null)
				NestedSupportChanged(this, EventArgs.Empty);

			RaisePropertyChanged("NestedSupport");
		}

		/// <summary>
		/// Signals that a property has changed.
		/// </summary>
		public event PropertyChangedEventHandler PropertyChanged;

		/// <summary>
		/// Raises the <see cref="PropertyChanged"/> event.
		/// </summary>
		/// <param name="property">Name of the property that changed.</param>
		protected void RaisePropertyChanged(string property)
		{
			if (PropertyChanged != null)
				PropertyChanged(this, new PropertyChangedEventArgs(property));

			_isChanged = true;
		}

		#endregion

		/// <summary>
		/// Checks that the object has been properly initialized through 
		/// a call to <see cref="Initialize"/> or <see cref="ISupportInitialize.BeginInit"/> 
		/// and <see cref="ISupportInitialize.EndInit"/>. 
		/// </summary>
		/// <exception cref="InvalidOperationException">The object was not initialized.</exception>
		private void EnsureInitialized()
		{
			// This is costly. Should we avoid checking IsChanged?
			if (RequiresInitialize)
			{
				throw new InvalidOperationException(NotInitialized);
			}
		}
	}
}